package gameAppLayer;


import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;

import old.gui.GUIViewManager;

import de.lessvoid.nifty.Nifty;
import eventManager.AppEvent;
import eventManager.EventManager;
import eventManager.EventPortal;

import gameAppLayer.enums.Constants;
import gameAppLayer.gui.GUIStateMachine;

import gameAppLayer.stateMachine.GameStateMachine;
import gameAppLayer.stateMachine.strategyState.GlobalLODControl;

import testClasses.TestingSystem;
import testClasses.misc.TestGameSettingsDefaults;
import utilities.AssetFileFinder;
import utilities.ExternalDataLoader;
import utilities.XMLLoader;

import com.jme3.app.SimpleApplication;
import com.jme3.asset.AssetKey;
import com.jme3.collision.CollisionResults;
import com.jme3.input.FlyByCamera;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.math.Ray;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.niftygui.NiftyJmeDisplay;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.BloomFilter;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.scene.Geometry;
import com.jme3.scene.Spatial.CullHint;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeContext.Type;

public class MyMainApp extends SimpleApplication {

	private static final Logger logger = Logger.getLogger(MyMainApp.class.getName());
	
	public int requiredMemory = 2048; //NOTE: Refactor into settings file later
	public GAERROR error;
	public GASOLUTION solution;
	public EventManager eventManager;
	public TestingSystem testSystem;
//	public StrategyCamera stratCam; //temporary until full system is setup
//	public StrategyCameraWatcher camWatcher;
	
	//Review--may not need these
	public GUIViewManager guiManager;	
	
	//New system, to take over from above
	public GameStateMachine gameStateMachine;
	public GUIStateMachine guiStateMachine;
	
	public GameSettings gameSettings;	
	
	@Override
	public void simpleInitApp() {
		logger.log(Level.INFO, "Starting");//
		
		flyCam.setEnabled(false); //disable flyCam
		
		RootNodePortal rootPortal = new RootNodePortal(this.rootNode);
		
		AssetFileFinder fileFinder = new AssetFileFinder(Constants.rootDir);
		HashMap<String, String> files = fileFinder.findAllFiles();
		
		//Load external files
		ExternalDataLoader externalLoader = new ExternalDataLoader();
        try {
        	externalLoader.execute();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (ClassNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
        ExternalData externalData = externalLoader.getData();
        logger.log(Level.INFO, "Loaded ExternalData");
		
		//Load game assets
        AssetPortal assetPortal = new AssetPortal(assetManager);
		AssetPreLoader assetPreLoader = new AssetPreLoader(assetManager, externalData);
		boolean preLoadCheck = assetPreLoader.init(files);
		//@SuppressWarnings("rawtypes")
		//HashMap<String, AssetKey> assetMap = new HashMap<String, AssetKey>();
		
		//Load XML files
//        XMLLoader xmlLoader = new XMLLoader();
//        try {
//			xmlLoader.execute();
//		} catch (IOException e1) {
//			// TODO Auto-generated catch block
//			e1.printStackTrace();
//		} catch (ClassNotFoundException e1) {
//			// TODO Auto-generated catch block
//			e1.printStackTrace();
//		}
//        XMLData xmlData = xmlLoader.getData();
//        logger.log(Level.INFO, "Loaded XMLData");				
//		//Load game assets		
//		AssetPreLoader assetPreLoader = new AssetPreLoader(assetManager, xmlData);
//		boolean preLoadCheck = assetPreLoader.init();
		
		
		
		//Load application event manager, register base event types
        eventManager = new EventManager();
        EventPortal eventPortal = new EventPortal(eventManager);
        
//        registerBaseGameEvents();        
    	
        //Init fonts here (is this handled in externalData loader?)
        
    	//Load language dll, user settings here (is this handled in externalData loader?)
        
    	//Load script manager here
        
       
        
        //Start GameStateMachine
		gameStateMachine = new GameStateMachine(
				inputManager, 
				cam,
				externalData);
        
		//Add bloom postprocessor
		FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
		BloomFilter bloom = new BloomFilter(BloomFilter.GlowMode.Objects);
//		bloom.setExposurePower(5.0f);
//		bloom.setBloomIntensity(2.0f);
//		bloom.setExposureCutOff(0.01f);
//		bloom.setBlurScale(2.0f);
		fpp.addFilter(bloom);		
		viewPort.addProcessor(fpp);
		
		//Logic structure that enables testSystem to be used
//		boolean check;
//		if (testSystem != null) {
//			logger.log(Level.INFO, "MyMainApp: TestSystem running");
//			//this.gameSettings = testSystem.settingsConfig.settings;
//			
//			testSystem.eventManager = this.eventManager;
//			testSystem.inputManager = this.inputManager;
//			testSystem.node = this.rootNode;
//			testSystem.app = this;
//			testSystem.externalData = externalData;			
//			
//			boolean check1 = testSystem.addTests();
//			
//			try {
//				check = testSystem.executeActiveTests();
//			} catch (FileNotFoundException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			} catch (IOException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			} catch (ClassNotFoundException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}
//		}
//		else {
			logger.log(Level.INFO, "MyMainApp: Starting...");
			
			TestGameSettingsDefaults testSettings = new TestGameSettingsDefaults(externalData);
			this.gameSettings = testSettings.settings;
			
			gameStateMachine.start();
//			Object obj[] = new Object[] {gameSettings};
//			gameStateMachine.handleEvent(new AppEvent("GameStateToStrategy", obj));
//		}
		
		//eventManager.queueEvent(new GameStateToStrategyEvent(System.currentTimeMillis(), gameSettings));
		
//		//Initialize Nifty-GUI		
		NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(assetManager, inputManager, audioRenderer, guiViewPort);
		Nifty nifty = niftyDisplay.getNifty();
//		nifty.fromXml("filepath", "start");			
		guiViewPort.addProcessor(niftyDisplay);
//		
//		nifty.loadStyleFile("nifty-default-styles.xml");
//		nifty.loadControlFile("nifty-default-controls.xml");
//		
//		//Start GUIStateMachine
//		guiStateMachine = new GUIStateMachine(assetManager);
//		guiStateMachine.start(gameStateMachine, nifty);
//		
//		nifty.gotoScreen("MAIN_MENU");
		
		
		
		
		
	}
	
	public void simpleUpdate(float tpf){
    	
		//guiManager.update();
//    	if (testSystem!=null) {
//    		testSystem.update(tpf);
//    	}		
		
		gameStateMachine.update(tpf);
		//nifty.render(true); //unsure if this is needed...?
		
    	//run through eventManager queue
    	eventManager.procEvents(1000);    	
    }
	
//	private boolean registerBaseGameEvents() {
//		logger.log(Level.INFO, "MyMainApp: registerBaseGameEvents()");
//    	if (eventManager!=null)
//    	{
//    		for (ECodeEventList event : ECodeEventList.values())
//    		{
//    			eventManager.addCodeEventType(event);    			
//    		}
//    		return true;
//    	}
//    	else
//    		return false;
//	}
    
    public AppSettings getAppSettings()
    {return settings;}
    
    public EventManager getEventManager()
    {return eventManager;}
    
    public GUIViewManager getGUIStateManager()
    {return guiManager;}
    
    //Used to run application from outside test harness system
	public boolean testStart(TestingSystem testSystem) {
		logger.log(Level.INFO, "TestStart()");
		
		this.testSystem = testSystem;
		this.start();
		return true;
	}
	
	public static void main(String[] args) 
	{
		MyMainApp app = new MyMainApp();
		app.start();
	}
	
}



//Check for existing instances of the game
//http://javalandscape.blogspot.com/2008/07/single-instance-from-your-application.html

////REINSTATE AT SOME POINT, at start of simpleInitApp()
///*RandomAccessFile randomFile = null;
//try {
//	randomFile = new RandomAccessFile("E:/Documents and Settings/RJ/workspace/Astral Clade/assets/Lockfile.txt","rw");
//	//randomFile = new RandomAccessFile("C:/Documents and Settings/rmeyers/workspace/Astral Clade/assets/Lockfile.txt","rw");
//} catch (FileNotFoundException e) {
//	logger.log(Level.FINE, "DarkMatterApp, Lock file not found", getClass().getName());
//				
//	try {
//		throw new GameAppError(error.GAERR_LOCK_FILE_NOT_FOUND);
//	} catch (GameAppError err) {
//		err.handle(); //TODO: Must write handle code			
//	}			
//}
//
//FileChannel channel = randomFile.getChannel();
//
//try {
//	//If cannot get lock on Lockfile, exit.
//	if(channel.tryLock()==null){
//		logger.log(Level.FINE, "DarkMatterApp, File lock not acquired, exiting...", getClass().getName());
//		stop();
//	}
//} catch (IOException e) {
//	// TODO Auto-generated catch block
//	logger.log(Level.FINE, "DarkMatterApp, File lock IO Error--exiting...", getClass().getName());
//	stop();
//}*/
